import { newArrayProto } from "./array";
import Dep from "./dep";

class Observer {
  constructor(data) {
    //给每个对象增加搜集功能
    this.dep = new Dep();
    Object.defineProperty(data, "__ob__", {
      value: this,
      enumerable: false, //不可枚举，循环的时候无法获取到，避免死循环
    });
    // data.__ob__ = this;
    if (Array.isArray(data)) {
      //重写数组中的方法
      data.__proto__ = newArrayProto;
      // this.observeArray(data);
    } else {
      this.walk(data);
    }
  }
  observeArray(data) {
    data.forEach((v) => observe(v));
  }
  walk(data) {
    //循环重新劫持对象
    Object.keys(data).forEach((key) => defineReactive(data, key, data[key]));
  }
}
function dependArray(value) {
  for (let i = 0; i < value.length; i++) {
    let current = value[i];
    current.__ob__ && current.__ob__.dep.depend();
    if (Array.isArray(current)) {
      dependArray(current);
    }
  }
}
export function defineReactive(target, key, value) {
  let childOb = observe(value); //对所有对象劫持,childOb.dep用来收集依赖
  let dep = new Dep(); //每个属性都有一个dep
  Object.defineProperty(target, key, {
    get() {
      if (Dep.target) {
        dep.depend(); //让这个属性 的收集器记住当前的watcher
        if (childOb) {
          childOb.dep.depend(); //让数组和对象本身也实现依赖收集
          if (Array.isArray(value)) {
            dependArray(value);
          }
        }
      }
      return value;
    },
    set(newValue) {
      if (value == newValue) {
        return;
      }
      observe(value);
      value = newValue;
      dep.notify(); //通知更新
    },
  });
}
export function observe(data) {
  if (typeof data !== "object" || data == null) {
    return;
  }

  if (data.__ob__ instanceof Observer) {
    return data.__ob__; //对象被代理过了
  }

  //如果一个对象被劫持过，就不需要再被劫持,增加一个实例判断
  return new Observer(data);
}
